/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Operations.Wavelet;

import Operations.CommonFunc;
import java.awt.Dimension;
import java.awt.image.BufferedImage;

/**
 *
 * @author littlechild
 */
public class WatermarkMaker {
    Wavelet wavelet=new Wavelet();
    public BufferedImage addWatermark(BufferedImage image,WatermarkKey wmkey){
        if(image==null)
            return null;
        int level=wmkey.level;
        int T1=wmkey.T1;
        int T2=wmkey.T2;
        double alpha=wmkey.alpha;
        double[][] ori = new double[image.getWidth()][image.getHeight()];
        for (int i = 0; i != image.getWidth(); ++i) {
            for (int j = 0; j != image.getHeight(); ++j) {
                ori[i][j] = CommonFunc.getGray(image.getRGB(i, j));
            }
        }
        Dimension LLsize = new Dimension();
        double [][]wave = wavelet.transform(ori, level, LLsize);
        double [][]key=new double[wave.length][wave[0].length];
        cern.jet.random.Normal norm=new cern.jet.random.Normal(0,1,cern.jet.random.Normal.makeDefaultGenerator());
        double abssum=0;    //use for check
        double z=0;         //used for check
        while(z<=alpha/2*abssum) {
            //LH
            for(int i=0;i<LLsize.getWidth();++i) {
                for(int j=round(LLsize.getHeight());j!=wave[0].length;++j) {
                    if(wave[i][j]>=T1) {
                        key[i][j]=norm.nextDouble();
                        wave[i][j]+=alpha*Math.abs(wave[i][j])*key[i][j];
                        if(wave[i][j]>T2) {
                            z+=wave[i][j]*key[i][j];    
                            abssum+=(wave[i][j]>0) ? wave[i][j]: -wave[i][j];
                        }
                    }
                }
            }
            //HL && HH
            for(int i=round(LLsize.getWidth());i!=wave.length;++i) {
                for(int j=0;j!=wave[0].length;++j) {
                    if(wave[i][j]>=T1) {
                        key[i][j]=norm.nextDouble();
                        wave[i][j]+=alpha*Math.abs(wave[i][j])*key[i][j];          
                        if(wave[i][j]>T2) {
                            z+=wave[i][j]*key[i][j];
                            abssum+=(wave[i][j]>0) ? wave[i][j]: -wave[i][j];
                        }
                    }
                }
            }
        }
        wmkey.key=key;
        double [][]transformed=wavelet.invTransform(wave, level);
        BufferedImage returnImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
        for (int i = 0; i != returnImage.getWidth(); ++i) {
            for (int j = 0; j != returnImage.getHeight(); ++j) {
                int rgb = round(transformed[i][j]);
                rgb=rgb<0 ? 0 : rgb;
                rgb=rgb>0xff ? 0xff:rgb;
                rgb = rgb | (rgb << 8) | (rgb << 16);
                returnImage.setRGB(i, j, rgb);
            }
        }
        return returnImage;
    }
    public boolean testWatermark(BufferedImage image, WatermarkKey wmkey) {
        int level=wmkey.level;
        int T1=wmkey.T1;
        int T2=wmkey.T2;
        double alpha=wmkey.alpha;
        double[][] ori = new double[image.getWidth()][image.getHeight()];
        for (int i = 0; i != image.getWidth(); ++i) {
            for (int j = 0; j != image.getHeight(); ++j) {
                ori[i][j] = CommonFunc.getGray(image.getRGB(i, j));
            }
        }
        Dimension LLsize = new Dimension();
        double [][]wave = wavelet.transform(ori, level, LLsize);
        double z=0;
        double abssum=0;
        //LH
        for(int i=0;i<LLsize.getWidth();++i) {
            for(int j=round(LLsize.getHeight());j!=wave[0].length;++j) {
                if(wave[i][j]>T2) {
                    z+=wave[i][j]*wmkey.key[i][j];
                    abssum+=(wave[i][j]>0) ? wave[i][j]: -wave[i][j];
                }
            }
        }
        for(int i=round(LLsize.getWidth());i!=wave.length;++i) {
            for(int j=0;j!=wave[0].length;++j) {
                if(wave[i][j]>T2) {
                    z+=wave[i][j]*wmkey.key[i][j];
                    abssum+=(wave[i][j]>0) ? wave[i][j]: -wave[i][j];
                }
            }
        }
        if(z>alpha/2*abssum)
            return true;
        else 
            return false;
    }

    private int round(double a) {
        if(a<0)
            return (int)(a-0.5);
        else
            return (int)(a+0.5);
    }
}
